//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<task_manager.h>
///	@path	~/src/engine/xcore/
///	@date	2007/12/21
///	@desc	Task manager, managed common tasks.

#pragma once

#include "xeres.h"

#include "lib/utilities/time.h"
#include "lib/utilities/callback.h"
#include "lib/system/thread_pool.h"

namespace xeres {

	typedef int TaskReturn;

	// common value for task result
	enum CommonTaskReturn
	{
		// Task is failed.
		TASK_FAILED = -1,
		// Task is success.
		TASK_SUCCESS = 0,
		// User defines custom result after this value.
		TASK_USER 
	};

	// task status
	enum TaskStatus
	{
		// Task slot is idle.
		TASK_STATUS_IDLE	= -1 ,
		// Task is working.
		TASK_STATUS_WORKING ,
		// Task is completed.
		TASK_STATUS_COMPLETED ,
		// Task is canceled.
		TASK_STATUS_CANCELED ,
	};

	// task result
	struct TaskResult
	{
		TaskStatus		status : 16;
		TaskReturn		ret : 16;

		TaskResult( TaskStatus status , TaskReturn ret )
			: status( status ) , ret( ret )
		{
		}
	};

	/*!
		\class	TaskManager
		\brief	We define a serial of slots that task can push into,
				than a 'TaskSlot' returned, to indicate which slot is linked.
				When the task is finished, the slot will be set to active state,
				and the completion routine will be called.
				This mechanism is designed to solve multi-threading task problem.
	*/
	class TaskManager : public ThreadPool
	{
	protected:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		TaskManager( void );

		/// \dtor
		~TaskManager( void );

		//@}

		/// \name Internal manipulation methods
		//@{

		/*!
			\brief		Initialize task manager.
		*/
		void Initialize( size_t init_task_size , int worker_count , bool lower_priority , const std::vector<bool> * processors );

		/*!
			\brief		Finalize task manager.
		*/
		void Finalize( void );

		/*!
			\brief		Per-frame call, resolve pending completion & canceled, and limit in a prediction time.
		*/
		void Resolve( Time predict );

		//@}

	public:

		/// \name Manipulation Interfaces
		//@{

		/*!
			\brief		Insert a new routine call (asynchronized).
		*/
		void InsertAsyncTask( function<TaskReturn(void)> routine , function<void(TaskResult)> completion );

		//@}

	private:

		/// \brief Common task is used for wrapping very simple routine calls.
		class _CommonTask : public ThreadPool::Job
		{
		public:

			/// \ctor
			_CommonTask( void );

			/// \dtor
			virtual ~_CommonTask( void );

		//@ interface
			
			/*!
				\brief		Execute job. Called when job Starts.
			*/
			virtual void Execute( void );

			/*!
				\brief		Job done callback.
			*/
			virtual void Done( void );

			/*!
				\brief		Call when job canceled.
			*/
			virtual void Canceled( void );

		//@ local

			/*!
				\brief		Prepare next task.
			*/
			void PrepareNext( function<TaskReturn(void)> routine , function<void(TaskResult)> completion );

			/*!
				\brief		Task is completed, free all routines.
			*/
			void FreeTask( void );

		private:

			friend class TaskManager;

		//@ data
			volatile TaskStatus				m_status;
			TaskReturn						m_return;
			function<void(TaskResult)>		m_completion;
			function<TaskReturn(void)>		m_routine;
			_CommonTask * 					m_next;

		public:
			DEBUG_RUN( int					m_id );
		};

		DEBUG_RUN( void TaskList( void ) );

		// take a task & run
		_CommonTask * TakeTask( _CommonTask * begin , _CommonTask *& last );

	//@ data

		_CommonTask *	 	m_workingTasks;
		_CommonTask * 		m_freeTasks;

		bool				m_destructing;
		bool				m_spare0[3];
	};

} // namespace xeres
